package com.example.gkgyservice.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.example.gkgyservice.domain.AddDataVo;
import com.example.gkgyservice.domain.OpcUaServer;
import com.example.gkgyservice.domain.ServiceData;
import com.example.gkgyservice.service.OpcUaSocketService;
import com.example.gkgyservice.thread.SocketThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author:xec
 * @date:2022/12/5 9:52
 **/
@Service
@Slf4j
public class OpcUaSocketServiceImpl implements OpcUaSocketService {

    static public List<OpcUaServer> opcUaServerList = new ArrayList<>();

    static String path = System.getProperty("user.dir") + "/sgp/gkgt-server-data.sgp";


    static {
        File file = new File(path);
        if (!file.getParentFile().exists()) {
            log.info("文件夹不存在创建文件夹");
            file.getParentFile().mkdirs();
        }
        if (file.exists()) {
            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                reader.close();
                String content = sb.toString();
                if (content.length() > 0) {
                    log.info("读取文件");
                    JSONArray objects = JSON.parseArray(content);
                    for (Object object : objects) {
                        OpcUaServer opcUaServer1 = JSON.parseObject(object.toString(), OpcUaServer.class);
                        opcUaServerList.add(opcUaServer1);
                    }
                }
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else {
            log.info("文件不存在，创建文件");
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @PostConstruct
    public void start() {
        // 初始化服务端socket并且绑定9999端
        //等待客户端的连
        new Thread(new Runnable() {
            @Override
            public void run() {
                ServerSocket serverSocket = null;
                try {
                    serverSocket = new ServerSocket(8888);
                    while (true) {
                        try {
                            Socket socket = null;
                            System.out.println("等待连接");
                            socket = serverSocket.accept();
                            System.out.println("有socket连接");
                            new SocketThread(socket).start();
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }


    @Override
    public Map<String, Object> editValue(List<OpcUaServer> opcUaServers) {
        for (OpcUaServer opcUaServer : opcUaServers) {
            for (OpcUaServer uaServer : opcUaServerList) {
                if (opcUaServer.getUid().equals(uaServer.getUid())) {
                    for (ServiceData serviceData : opcUaServer.getNodeList()) {
                        for (ServiceData data : uaServer.getNodeList()) {
                            if (serviceData.getDisplayName().equals(data.getDisplayName())) {
                                data.setNodeValue(serviceData.getNodeValue());
                            }
                        }
                    }
                }
            }
        }
        File file = new File(path);
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(JSON.toJSONString(opcUaServerList).getBytes());
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);
        map.put("data", opcUaServers);
        return map;
    }

    @Override
    public Map<String, Object> addData(List<AddDataVo> addDataVos, String uid) {
        List<ServiceData> nodeList = new ArrayList<>();
        List<String> collect = opcUaServerList.stream().map(OpcUaServer::getUid).collect(Collectors.toList());
        int i = collect.indexOf(uid);
        if (i > 0) {
            for (OpcUaServer uaServer : opcUaServerList) {
                if (uaServer.getUid().equals(uid)) {
                    List<ServiceData> nodeList2 = uaServer.getNodeList();
                    List<ServiceData> nodeList1 = uaServer.getNodeList();
                    for (AddDataVo addDataVo : addDataVos) {
                        int flag = 0;
                        for (ServiceData serviceData : nodeList1) {
                            if (serviceData.getNodeName().equals(addDataVo.getVariableName())) {
                                flag = 1;
                            }
                        }
                        if (flag == 0) {
                            ServiceData serviceData1 = new ServiceData();
                            serviceData1.setNodeValue(addDataVo.getSaveValue());
                            serviceData1.setDisplayName(addDataVo.getVariableName());
                            serviceData1.setNodeId(addDataVo.getVariableIndex());
                            serviceData1.setNodeName(addDataVo.getVariableName());
                            serviceData1.setNodeType(addDataVo.getDataType());
                            nodeList2.add(serviceData1);
                        }
                    }
                    uaServer.setNodeList(nodeList2);
                }
            }
        } else {
            OpcUaServer opcUaServer = new OpcUaServer();
            opcUaServer.setUid(uid);
            for (AddDataVo addDataVo : addDataVos) {
                ServiceData serviceData = new ServiceData();
                serviceData.setNodeValue(addDataVo.getSaveValue());
                serviceData.setDisplayName(addDataVo.getVariableName());
                serviceData.setNodeId(addDataVo.getVariableIndex());
                serviceData.setNodeName(addDataVo.getVariableName());
                serviceData.setNodeType(addDataVo.getDataType());
                nodeList.add(serviceData);
            }
            opcUaServer.setNodeList(nodeList);
            opcUaServerList.add(opcUaServer);
        }

        File file = new File(path);
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write(JSON.toJSONString(opcUaServerList).getBytes());
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("data", opcUaServerList);
        map.put("code", 200);
        return map;
    }

    @Override
    public List<OpcUaServer> list(OpcUaServer opcUaServer) {
        if (opcUaServer.getUid() != null) {
            for (OpcUaServer uaServer : opcUaServerList) {
                if (opcUaServer.getUid().equals(uaServer.getUid())) {
                    List<OpcUaServer> opcUaServers = new ArrayList<>();
                    opcUaServers.add(uaServer);
                    return opcUaServers;
                }
            }
        }
        return opcUaServerList;
    }

    @Override
    public OpcUaServer selectByName(String uid, String name) {
        if (uid == null) {
            return new OpcUaServer();
        } else if (name == null) {
            for (OpcUaServer opcUaServer : opcUaServerList) {
                if (opcUaServer.getUid().equals(uid)) {
                    return opcUaServer;
                }
            }
        } else {
            for (OpcUaServer opcUaServer : opcUaServerList) {
                if (opcUaServer.getUid().equals(uid)) {
                    OpcUaServer opcUaServer1 = new OpcUaServer();
                    opcUaServer1.setUid(uid);
                    ArrayList<ServiceData> nodeList = new ArrayList<>();
                    for (ServiceData serviceData : opcUaServer.getNodeList()) {
                        if (serviceData.getNodeName().contains(name)) {
                            nodeList.add(serviceData);
                        }
                    }
                    opcUaServer1.setNodeList(nodeList);
                    return opcUaServer1;
                }
            }
        }
        return new OpcUaServer();
    }

    @Override
    public void editFlag(Integer value1) {
        flag = 1;
        value = value1;
    }

    @PostConstruct
    public void dataSimulation() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    for (OpcUaServer opcUaServer : opcUaServerList) {
                        List<ServiceData> nodeList = opcUaServer.getNodeList();
                        List<ServiceData> nodes = new ArrayList<>();
                        for (ServiceData serviceData : nodeList) {
                            for (int j = 1; j < 13; j++) {
//                                if (serviceData.getNodeName().equals("St1.OKCount["+j+"]") || serviceData.getNodeName().equals("St1.NGCount["+j+"]")) {
//                                    Object nodeValue = serviceData.getNodeValue();
//                                    int i = 0;
//                                    if (nodeValue!=null) {
//                                        i = Integer.parseInt(nodeValue.toString());
//                                        i += 1;
//                                    }
//                                    serviceData.setNodeValue(i);
//                                }
//                                if (serviceData.getNodeName().equals("St1.CycleTime["+j+"]")){
//                                    int i = RandomUtil.randomInt(10000,200000);
//                                    serviceData.setNodeValue(i);
//                                }
                            }
                            nodes.add(serviceData);
                        }
                        opcUaServer.setNodeList(nodes);
                    }
                    try {
                        File file = new File(path);
                        try {
                            FileOutputStream fileOutputStream = new FileOutputStream(file);
                            fileOutputStream.write(JSON.toJSONString(opcUaServerList).getBytes());
                            fileOutputStream.close();
                        } catch (FileNotFoundException e) {
                            throw new RuntimeException(e);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }).start();
    }

    public static int flag = 0;

    public static int value =  16;

    @PostConstruct
    public void changeData() {
        String[] s = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
                "a","b","c","d","e","f","g","j","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
        int length = s.length;
        List<String> s1 = new ArrayList<>();
        s1.add("product.barcode1");
        s1.add("product.barcode1");
        s1.add("product.barcode2");
        s1.add("product.barcode3");
        s1.add("product.barcode4");
        s1.add("product.barcode5");
        for (int i = 0; i < 20; i++) {
            s1.add("product.op"+(i+1)+"0.barcode1");
            s1.add("product.op"+(i+1)+"0.barcode2");
            s1.add("product.op"+(i+1)+"0.barcode3");
            s1.add("product.op"+(i+1)+"0.barcode4");
            s1.add("product.op"+(i+1)+"0.barcode5");
            s1.add("data.op"+(i+1)+"0.barcode1");
            s1.add("data.op"+(i+1)+"0.barcode2");
            s1.add("data.op"+(i+1)+"0.barcode3");
            s1.add("data.op"+(i+1)+"0.barcode4");
            s1.add("data.op"+(i+1)+"0.barcode5");
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    for (OpcUaServer opcUaServer : opcUaServerList) {
                        List<ServiceData> nodeList = opcUaServer.getNodeList();
                        List<ServiceData> nodes = new ArrayList<>();
                        for (ServiceData serviceData : nodeList) {
                            if (serviceData.getNodeName().equals("St1.RunTime")) {
                                int i = Integer.parseInt(serviceData.getNodeValue().toString());
                                i += 1;
                                serviceData.setNodeValue(i);
                            }
                            if (serviceData.getNodeName().contains("existence")){
                                int i = RandomUtil.randomInt(0,6);
                                serviceData.setNodeValue(i);
                            }
                            if (opcUaServer.getUid().equals("PLC-2019-JC-XN")){
                                if (serviceData.getNodeName().contains("data_pc_plc.plc_request.data1")){
//                                    for (int i = 0; i < 1000; i++) {
//                                        if (serviceData.getNodeValue().equals(16)) {
//                                            try {
//                                                Thread.sleep(10);
//                                            } catch (InterruptedException e) {
//                                                throw new RuntimeException(e);
//                                            }
//                                            log.info("{}：{}工位变0",opcUaServer.getUid(),serviceData.getDisplayName());
//                                            serviceData.setNodeValue(0);
//                                        }else {
//                                            try {
//                                                Thread.sleep(10);
//                                            } catch (InterruptedException e) {
//                                                throw new RuntimeException(e);
//                                            }
//                                            log.info("{}：{}工位变16",opcUaServer.getUid(),serviceData.getDisplayName());
//                                            serviceData.setNodeValue(16);
//                                        }
//                                    }
                                }
                            }
                            if (serviceData.getNodeName().contains("data_pc_plc.plc_request.data")){
//                                serviceData.setNodeValue(0);
                                int i = RandomUtil.randomInt(1, 2);
                                if (i==1){
                                    if (!serviceData.getNodeValue().equals("16")&&flag==1) {
                                        log.info("{}：{}工位变16",opcUaServer.getUid(),serviceData.getDisplayName());
                                        serviceData.setNodeValue(value);
                                    }
                                }
                            }
                            if(s1.contains(serviceData.getNodeName().toLowerCase())){
                                String value = new String();
                                for (int i = 0; i < 10; i++) {
                                    int i1 = RandomUtil.randomInt(length);
                                    value += s[i1];
                                }
                                serviceData.setNodeValue(value);
                            }
                            nodes.add(serviceData);
                        }
                        opcUaServer.setNodeList(nodes);
                    }
                    try {
                        File file = new File(path);
                        try {
                            FileOutputStream fileOutputStream = new FileOutputStream(file);
                            fileOutputStream.write(JSON.toJSONString(opcUaServerList).getBytes());
                            fileOutputStream.close();
                        } catch (FileNotFoundException e) {
                            throw new RuntimeException(e);
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        flag = 0;
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }).start();
    }
}